#!/usr/bin/env python
# -*- coding: utf-8 -*-


from os import makedirs
from os import sep
from os import path
from sqlite3 import dbapi2 as sqlite
import socket


#Protocolo utilizado entre o cliente e o servidor
AUTENTICAR = "A"
VOTAR = "V"
IMAGEM = "I"
PARTIDO = "P"
CANDIDATO ='C'
ERROR = "E"
OK = 'OK'
DIVISOR='|'

#Arquivos e pastas
TEMP='arquivos' # 
BANCO=TEMP+sep+'cliente.db'
IMAGEM_DEFAULT = TEMP+sep+'default.jpg'

class Cliente(object):
    
    def __init__(self,ip='localhost',porta=2727):
        self.ip = ip
        self.porta = porta
        
        if not path.isdir(TEMP): # Se nao existe a pasta, cria
            makedirs(TEMP)
            
        self.conn = self.criar_banco_dados(BANCO) # Cria a conexão com o banco de dados
        
    def criar_banco_dados(self,caminho):
        """
        Cria o banco de dados do cliente e retorna a conexão com ele,
        se o banco já existir apenas retorna a conexão
        """
        try:
            if not path.exists(caminho):
                conn = sqlite.connect(caminho)
                cursor = conn.cursor()
                cursor.execute('CREATE TABLE Partidos(id INTEGER primary key NOT NULL UNIQUE ,nome text,numero text NOT NULL UNIQUE)')
                cursor.execute('CREATE TABLE Politicos(id INTEGER primary key,nome text NOT NULL,numero text NOT NULL UNIQUE)')
                cursor.close()
                conn.commit() # Salva as alterações no bd
            else:
                conn = sqlite.connect(BANCO)
            return conn
        except:
            raise Exception('Erro na conexao do banco de dados')
           
    
    def votar(self,numero):
        """
        Envia ao servidor o voto do eleitor para ser computado.
        """
        
        resposta,buffer = self._requisitar(VOTAR,numero) 
        print buffer
        if resposta!=ERROR:
            return buffer
        else:
            
            raise Exception(buffer)  # Mudar excecao
    
    def autenticar(self,cpf):
        """
        Faz a autenticação do eleitor com o servidor, retorna o tipo de cargo
        que será votado na eleição.
        """
        
        self.chave = cpf
        resposta,buffer = self._requisitar(AUTENTICAR,cpf)
        if resposta!=ERROR:
            print "CARGO:",buffer
            return buffer
        else:
            raise Exception(buffer) #Mudar

    def tenta_conectar(self):
        """
        Tenta conexão com o servidor para saber se o ip escolhido pelo usuário é válido
        """
        try:
            sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
            sock.connect((self.ip,self.porta))
                
        except:
            raise Exception('Erro ao tentar se conectar')
    
    def partido_politico(self,numero):
        """
        Retorna o nome do partido passado por parametro, se o partido não existir
        no banco de dados do cliente, ele faz uma requisição ao servidor.
        """
        
        cursor = self.conn.cursor()
        cursor.execute('SELECT nome FROM Partidos WHERE numero=?',(numero,))
        tupla = cursor.fetchone() # Pega a primeira aparição da busca
        
        if tupla:
            
            partido=tupla[0]
            print 'PESQUISA NO CLIENTE:',partido
        else:        
            resposta,buffer = self._requisitar(PARTIDO,numero)
            if resposta!=ERROR:
                partido=buffer
                cursor.execute('INSERT INTO Partidos(nome,numero) VALUES(?,?)',(buffer,numero))
                self.conn.commit()
            else:
                raise Exception(buffer) # MUdar
        
        cursor.close()     
        return partido
            
    def nome_cadidato(self,numero):
        """
        Retorna o nome do candidato, primeiro procura no banco do cliente
        depois se não existir o numero ele faz um pedido ao servidor.
        """
        cursor = self.conn.cursor()
        cursor.execute('SELECT nome FROM Politicos WHERE numero=?',(numero,))
        tupla = cursor.fetchone()
        politico=''
        
        if tupla:
            
            politico=tupla[0] 
            print 'PESQUISA NO CLIENTE:',politico
        
        else:        
            resposta,buffer = self._requisitar(CANDIDATO,numero)
            if resposta!=ERROR:
                politico=buffer
                cursor.execute('INSERT INTO Politicos(nome,numero) VALUES(?,?)',(buffer,numero))
                self.conn.commit()
            else:
                raise Exception(buffer) # MUdar
        
        cursor.close()        
        return politico
                    
    
    def imagem(self,numero):
        """
        Retorna o caminho da imagem se a ela não existir na pasta de arquivos
        faz o pedido ao servidor.
        """
        
        imagem = TEMP+sep+numero+'.jpg'
                        
        if not path.exists(imagem):            
            
            resposta,buffer = self._requisitar(IMAGEM,numero)
            
            if resposta!=ERROR:
                arq =open(imagem,'wb')    # Cria um arquivo e escreve nele a 
                arq.write(buffer)         # imagem enviada pelo servidor
                arq.close()
            elif path.exists(IMAGEM_DEFAULT):
                imagem = IMAGEM_DEFAULT
            else:
                raise Exception('Não existe imagem')

        return imagem
    
    def _requisitar(self,tipo,texto):
        """
            Fazer o pedido ao servidor e retorna as
            informações enviada por ele
        """
        try:
            
            sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
            sock.connect((self.ip,self.porta))
            sock.send(tipo+DIVISOR+self.chave+DIVISOR+texto) #ex.: V|08212456789|13
            texto='' # Retorno da requisicao
            
            while 1:
                
                buffer = sock.recv(1024)
                texto+=buffer
                if not buffer:  # Quando o servidor não enviar mais nada
                    break       # sai do laço
                
            return tuple(texto.split(DIVISOR,1))
                
        except:
            print 'Erro'
        
if __name__ == '__main__':
    a = Cliente()
    #a.votar('13')
    #a.nome_cadidato('2222')
    print a.autenticar('08201540409')
    #a.partido_politico('13')
    #print a.nome_cadidato('13')
    #print a.imagem('13')
    a.votar('13')
    #cursor = a.conn.cursor()
    #cursor.execute('INSERT INTO Politicos(nome,numero) VALUES (?,?)',('Tiririca','2222'))
    #cursor.execute('SELECT * FROM Politicos')
    #print cursor.fetchall()
    #a.conn.commit()
        
        
    
    
